/*
 * Copyright 2013 HVTTGROUP
 * http://hvttgroup.com
 *
 */
package com.hvtt.web.models.datatable;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.ObjectUtils;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;

/**
 *
 * Class template Lazy for initialize data to dataTable with options :<br/>
 * @author Nguyễn Hoàng Danh
 * @version 1.0
 *
 * @param dataSource is List<DBObject> read from database
 * @param filterFields is Array fields you want filter
 *
 */
public class DefaultLazyDataModel<T> extends LazyDataModel<T> {

    private List<T> dataSource;
    private Field[] filterFields;
    private String filterMode="startsWith";
    public DefaultLazyDataModel(List<T> dataSource, Field[] filterFields) {
        this.dataSource = dataSource;
        this.filterFields = filterFields;
    }

    @Override
    public T getRowData(String rowKey) {
        for (T obj : dataSource) {
            if (String.valueOf(ObjectUtils.hashCode(obj)).equalsIgnoreCase(rowKey)) {
                return obj;
            }
        }
        return null;
    }

    @Override
    public Object getRowKey(T obj) {
        return String.valueOf(ObjectUtils.hashCode(obj));
    }

    @Override
    public Object getWrappedData() {
        return this.dataSource;
    }

    public List<T> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, String> filters) {
        List<T> data = new ArrayList();
        if (filters.isEmpty()) {
            data.addAll(dataSource);
        } else {
            String filterValue = filters.get("globalFilter");
            boolean globalMatch = false;
            for (T obj : dataSource) {
                for (Field field : filterFields) {
                    try {
                        field.setAccessible(true);
                        String value = String.valueOf(field.get(obj)).toLowerCase();//gia tri property
                        if (value != null && value.toLowerCase().contains(filterValue)) {
                            globalMatch = true;
                            break;
                        }
                    } catch (IllegalArgumentException | IllegalAccessException ex) {
                        globalMatch = false;
                    }
                }
                if (globalMatch) {
                    data.add(obj);
                    globalMatch = false;
                }
            }
        }
        if (sortField != null) {
            Collections.sort(data, new DefaultLazyDataSorter(sortField, sortOrder));
        }
        int dataSize = data.size();
        this.setRowCount(dataSize);
        if (dataSize > pageSize) {
            try {
                return data.subList(first, first + pageSize);
            } catch (IndexOutOfBoundsException e) {
                return data.subList(first, first + (dataSize % pageSize));
            }
        } else {
            return data;
        }
    }
}